// 定义类
function MyPromise(executor) {
    let self = this;
    // 定义需要的参数和方法

    // 当前的状态
    self.status = 'waiting';
    // 成功的值
    self.value = null;
    // 失败的原因
    self.reason = null;
    // 保存等待状态时传入的方法
    self.onSuccessCallback = [];
    self.onFailCallback = [];


    // 需要的方法
    // 成功的执行方法
    function resolve(value) {
        // 设置状态为成功 - 不可逆转
        if (self.status == 'waiting') {
            self.status = 'success';
            self.value = value;

            // 执行保存的方法
            self.onSuccessCallback.forEach(item => item(self.value))
        }
    }
    // 失败的执行方法
    function reject(reason) {
        // 设置状态为失败 - 不可逆转
        if (self.status == 'waiting') {
            self.status = 'fail';
            self.reason = reason;

            // 执行保存的方法
            self.onFailCallback.forEach(item => item(self.reason))
        }
    }


    // 传入并且需要先立即执行的方法 (需要捕获异常)
    try {
        executor(resolve, reject);
    } catch (error) {
        reject(error)
    }

}

// 实现 then 方法 - 需要监听成功以及失败的方法
MyPromise.prototype.then = function (onSuccess, onFail) {

    // 判断传入的成功以及失败的参数是否为方法
    onSuccess = typeof onSuccess == 'function' ? onSuccess : res => res;
    onFail = typeof onFail == 'function' ? onFail : err => err;


    // 实现 .then 方法的穿透 xxx.then().then()
    return new MyPromise((resolve, reject) => {

        // 依据当前的状态值 分别执行对应的方法
        let self = this;
        let fn = null;
        // 成功
        if (self.status == 'success') {
            fn = onSuccess(self.value);
            fn instanceof MyPromise ? fn.then(resolve, reject) : resolve(fn);
        }
        // 失败
        if (self.status == 'fail') {
            fn = onFail(self.reason);
            fn instanceof MyPromise ? fn.then(resolve, reject) : reject(fn);
        }
        // 等待中
        if (self.status == 'waiting') {
            // 如果是等待状态 需要将传入的成功或失败方法保存 等状态值发生改变再执行
            self.onSuccessCallback.push(() => {
                fn = onSuccess(self.value);
                fn instanceof MyPromise ? fn.then(resolve, reject) : resolve(fn);
            })
            self.onFailCallback.push(() => {
                fn = onFail(self.reason);
                fn instanceof MyPromise ? fn.then(resolve, reject) : reject(fn);
            })
        }

    })

}

// 实现 catch 方法 - 需要传入失败的方法
MyPromise.prototype.catch = function (onFail) {
    return this.then(null, onFail)
}